package com.example.mysharding.algo;

import com.example.mysharding.bean.ShardingDataSource;
import com.example.mysharding.bean.ShardingProperties;
import io.micrometer.common.util.StringUtils;
import org.apache.shardingsphere.api.config.sharding.strategy.ComplexShardingStrategyConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.InlineShardingStrategyConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.ShardingStrategyConfiguration;
import org.apache.shardingsphere.core.strategy.route.hint.HintShardingStrategy;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

public class ShardingStrategyFactory {

    public ShardingStrategyFactory() {
    }

    public static ShardingStrategyConfiguration getShardingStrategy(String tableName, String columnName, ShardingProperties shardingProperties) {
        ShardingStrategyConfiguration strategyConfiguration = null;
        int size = getDataSourceSize(shardingProperties);
        String dsStartegy = shardingProperties.getDsStrategy();
        String[] columns = new String[10];
        if (StringUtils.isNotEmpty(columnName)) {
            columns = columnName.split(",");
        }

        int strategyType = -1;
        if (columns.length == 1) {
            strategyType = 0;
        } else if (columns.length > 1) {
            strategyType = 1;
        }

        switch (strategyType) {
            case 1:
                strategyConfiguration = buildRangeAndIdRangeComplexSharding(tableName, columnName, columns, size, dsStartegy);
                break;
            case 0:
                strategyConfiguration = buildPreciseShardingStrategy(tableName, columnName, size, dsStartegy);
                break;
            default:
                throw new RuntimeException("config-yaml sharding-tables error, key:" + tableName + ", value:" + columnName);
        }

        return strategyConfiguration;
    }

    public static ComplexShardingStrategyConfiguration buildPreciseShardingStrategy(String tableName, String columnName, Integer dataSourceSize, String dsStartegy) {
        return new ComplexShardingStrategyConfiguration(columnName, new ComplexAlgoAdaptor(tableName, columnName, null, dataSourceSize, dsStartegy));
    }

    public static InlineShardingStrategyConfiguration getDefaultDsStrategy(String bussinessId, Integer dataSourceSize) {
        return new InlineShardingStrategyConfiguration(bussinessId, "ds$->{" + bussinessId + "%" + dataSourceSize+"}");
    }

    public static ComplexShardingStrategyConfiguration buildRangeAndIdRangeComplexSharding(String tableName, String columnName, String[] columns, Integer dataSourceSize, String dsStartegy) {
        String[] strs = columnName.split(",");
        String[] timeRangeArr = new String[strs.length - 1];
        System.arraycopy(strs, 1, timeRangeArr, 0, strs.length - 1);
        return new ComplexShardingStrategyConfiguration(columnName, new ComplexAlgoAdaptor(tableName, columns[0], timeRangeArr, dataSourceSize, dsStartegy));
    }



    public static HintShardingStrategy buildHintShardingStrategy(String tableName, String columnName, ShardingProperties shardingProperties) {
        return null;
    }

    private static int getDataSourceSize(ShardingProperties shardingProperties) {
        Map<String, DataSource> dataSourceMap = new HashMap();
        Map<String, ShardingDataSource> shardingDataSourceMaps = shardingProperties.getShardingDataSources();
        return shardingDataSourceMaps.size();
    }
}
